<script setup>
import Toast from "@vant/weapp/dist/toast/toast";
import myCanvas from '@/utils/myCanvas'

import myTextarea from './myTextarea.vue';
import { imgUploadVerify } from '@/utils/auth'
import { ref, getCurrentInstance, onMounted, nextTick, watch } from 'vue';
import { onLoad } from '@dcloudio/uni-app'


const props = defineProps({
    imgNumList: {
        type: Array,
        default: () => []
    },
})

const emit = defineEmits(['imgNumClick'])


const instance = getCurrentInstance()

const queryParams = ref({
    baseImageUrl: '', // 图像图片
    maskImageUrl: '', // 涂抹图区域图片
    prompt: '', // 描述词
    num: 1 // 生成张数
})

let imgCanvas, smearCanvas, eraseCanvas

// 原图尺寸
const oldImgSize = ref({})

// 父盒子宽高
const contentDom = ref({})
// canvas宽高
const canvasDom = ref({})

// 是否正在绘制(画笔)
const isDrawing = ref(false);
// 记录上一个点
const lastPoint = ref({});
// 是否是橡皮擦模式
const isErase = ref(false);
// 橡皮擦位置
const eraserPosition = ref({ x: 0, y: 0 });
// 橡皮擦/线条大小
const sliderValue = ref(30)



watch(() => props.imgNumList, () => {
    if (props.imgNumList.length) {
        queryParams.value.num = props.imgNumList[0]
    }
}, { immediate: true, deep: true })


function createFn() {
    return new Promise(resolve => {
        if (!smearCanvas.hasDrawn(0, 0, smearCanvas.canvas.width, smearCanvas.canvas.height)) {
            return Toast.fail('请涂抹需要重绘的区域')
        }
        uni.canvasToTempFilePath({
            canvas: smearCanvas.canvas,
            destWidth: oldImgSize.value.width,
            destHeight: oldImgSize.value.height,
            success(res) {
                queryParams.value.maskImageUrl = res.tempFilePath
                resolve(queryParams.value)
            },
        }, instance)
    })
}


// 清除图片
function clearImg() {
    queryParams.value.baseImageUrl = ''
    imgCanvas.clearRect(0, 0, canvasDom.value.width, canvasDom.value.height)
    smearCanvas.clearRect(0, 0, canvasDom.value.width, canvasDom.value.height)
}

// 调整橡皮擦线条大小
function sliderDrag(e) {
    sliderValue.value = e.detail.value
}

// 手指抬起
function touchend() {
    isDrawing.value = false;
    eraseCanvas.clearRect(0, 0, eraseCanvas.canvas.width, eraseCanvas.canvas.height)
}

// 触摸移动
function touchmove(e) {
    if (!isDrawing.value) return
    // 画笔
    if (!isErase.value) {
        const newPoint = e.touches[0]; // 记录当前点
        smearCanvas.drawBrush(lastPoint.value.x, lastPoint.value.y, newPoint.x, newPoint.y, sliderValue.value, '#FFF')

        eraseCanvas.clearRect(0, 0, eraseCanvas.canvas.width, eraseCanvas.canvas.height)
        eraseCanvas.drawRoundedRect(newPoint.x, newPoint.y, sliderValue.value, sliderValue.value / 2, 'rgba(0,0,0,0.5)')

        lastPoint.value = newPoint; // 更新上一个点
    } else {
        const newPoint = e.touches[0]; // 记录当前点
        smearCanvas.smoothErase(lastPoint.value.x, lastPoint.value.y, newPoint.x, newPoint.y, sliderValue.value)
        eraseCanvas.clearRect(0, 0, eraseCanvas.canvas.width, eraseCanvas.canvas.height)
        eraseCanvas.drawRoundedRect(newPoint.x, newPoint.y, sliderValue.value, sliderValue.value / 2, 'rgba(0,0,0,0.5)')
        lastPoint.value = newPoint; // 更新上一个点
    }
}

// 触摸事件
function touchstart(e) {
    if (!queryParams.value.baseImageUrl) return
    isDrawing.value = true;
    lastPoint.value = e.touches[0]; // 记录起点
    eraserPosition.value = {
        x: e.touches[0].x,
        y: e.touches[0].y
    }
    eraseCanvas.drawRoundedRect(lastPoint.value.x, lastPoint.value.y, sliderValue.value, sliderValue.value / 2, 'rgba(0,0,0,0.5)')

}

// 绘制图片
function drawImage() {
    Toast.loading({
        message: '图片加载中...',
        duration: 0,
        forbidClick: true,
    })
    nextTick(() => {
        imgCanvas.init()
        smearCanvas.init()
        eraseCanvas.init()
        setTimeout(() => {
            imgCanvas.drawImage(queryParams.value.baseImageUrl, 0, 0, canvasDom.value.width, canvasDom.value.height,
                undefined,
                () => {
                    Toast.clear()
                },
            )
        }, 1000)
    })

}


// 计算图片宽高比及外部边框盒子的宽高
async function calculatePicAspectRatio(path) {
    const { width, height } = await uni.getImageInfo({ src: path })
    oldImgSize.value = {
        width,
        height
    }
    const widthRatio = contentDom.value.width / width;
    const heightRatio = contentDom.value.height / height;
    const scaleRatio = Math.min(widthRatio, heightRatio);


    // 计算缩放后的图片宽度和高度
    const scaledWidth = width * scaleRatio;
    const scaledHeight = height * scaleRatio;

    canvasDom.value = {
        width: scaledWidth,
        height: scaledHeight
    }
}

// 上传图片
async function uplaodImgFn() {
    const res = await imgUploadVerify()
    queryParams.value.baseImageUrl = res
    imgCanvas.clearRect(0, 0, canvasDom.value.width, canvasDom.value.height)
    smearCanvas.clearRect(0, 0, canvasDom.value.width, canvasDom.value.height)
    eraseCanvas.clearRect(0, 0, canvasDom.value.width, canvasDom.value.height)
    calculatePicAspectRatio(queryParams.value.baseImageUrl).then(() => {
        drawImage()
    })
}


// 图片数量选择
function imgNumClick(item) {
    queryParams.value.num = item
    emit('imgNumClick', queryParams.value.num)
}

onMounted(() => {
    uni.createSelectorQuery().in(instance).select('.canvas_box').boundingClientRect((res) => {
        contentDom.value.width = res.width
        contentDom.value.height = res.height
        imgCanvas = new myCanvas('imgCanvas', instance)
        smearCanvas = new myCanvas('smearCanvas', instance)
        eraseCanvas = new myCanvas('eraseCanvas', instance)
    }).exec()

})

onLoad((e) => {
    if (!e.item) return

    if (JSON.parse(e.item)?.imageFileUrl) {
        queryParams.value.baseImageUrl = JSON.parse(e.item)?.imageFileUrl
        nextTick(() => {
            setTimeout(() => {
                imgCanvas.clearRect(0, 0, canvasDom.value.width, canvasDom.value.height)
                smearCanvas.clearRect(0, 0, canvasDom.value.width, canvasDom.value.height)
                eraseCanvas.clearRect(0, 0, canvasDom.value.width, canvasDom.value.height)
                calculatePicAspectRatio(queryParams.value.baseImageUrl).then(() => {
                    drawImage()
                })
            }, 700)
        })
    }
})


defineExpose({ createFn })

const textareaStyle = {
    height: '166rpx'
}
</script>

<template>
    <div class='labourSelect'>
        <div class="title_box">
            <div>上传图片</div>
            <!-- <div class="explain" @click="onClickTitle">
                <i class="iconfont ai-icon-tishishuoming"></i>
                玩法说明
            </div> -->
        </div>
        <div class="canvas_box">
            <!--上传按钮-->
            <div class="upload_btn" v-if="!queryParams.baseImageUrl" @click="uplaodImgFn">
                <i class="iconfont ai-icon-shangchuancankaotu"></i>
                <div class="text">相册选择</div>
            </div>
            <!--删除-->
            <div v-else class="clearBox" @click="clearImg">
                <i class="iconfont ai-icon-shanchutupian"></i>
            </div>
            <canvas type="2d" id="imgCanvas" :style="{ width: `${canvasDom.width}px`, height: `${canvasDom.height}px` }"
                class="imgCanvas"></canvas>
            <canvas type="2d" id="smearCanvas" :style="{ width: `${canvasDom.width}px`, height: `${canvasDom.height}px` }"
                class="smearCanvas"></canvas>

            <canvas type="2d" id="eraseCanvas" :style="{ width: `${canvasDom.width}px`, height: `${canvasDom.height}px` }"
                class="eraseCanvas" @touchstart="touchstart" @touchmove.stop="touchmove" @touchend="touchend"></canvas>
        </div>

        <div class="eraseAndsmear">
            <div class="left" @click="isErase = !isErase">
                <div class="smear" :class="{ active: !isErase }">
                    <i class="iconfont ai-icon-tumo"></i>
                </div>
                <div class="erase" :class="{ active: isErase }">
                    <i class="iconfont ai-icon-cachu"></i>
                </div>
            </div>
            <div class="right">
                <van-slider :value="sliderValue" :min="15" :max="45" @drag="sliderDrag" bar-height="4px"
                    active-color="#83CD88" />
            </div>
        </div>



        <div class="textarea_box">
            <myTextarea v-model="queryParams.prompt" label="输入修改描述词" placeholder="客厅有灰色沙发，灯具，抽象画作,以白色客厅墙为背景"
                :textareaStyle="textareaStyle" :overlayStyle="{ background: 'transparent' }">
            </myTextarea>
        </div>

        <div class="title_box">参数设置</div>
        <div class="imgNum">
            <div class="imgNum_item" :class="{ active: item === queryParams.num }" v-for="item of imgNumList"
                @click="imgNumClick(item)">
                <div class="text">{{ item }}</div>
            </div>
        </div>
    </div>
</template>

<style lang='scss' scoped>
.labourSelect {
    .title_box {
        position: relative;
        font-size: 28rpx;
        font-weight: bold;
        color: var(--a-one-text-color);
        padding-left: 30rpx;
        margin: 40rpx 0 18rpx;
        display: flex;
        align-items: center;
        justify-content: space-between;

        &::before {
            content: '';
            position: absolute;
            left: 0;
            top: 50%;
            transform: translate(0, -50%);
            width: 12rpx;
            height: 18rpx;
            background: var(--a-main-color);
            border-radius: 6rpx;
        }

        .text {
            font-size: 24rpx;
            font-weight: normal;
        }

        .explain {
            font-size: 24rpx;
            color: var(--a-two-text-color);
            font-weight: normal;
            display: flex;
            align-items: center;
            gap: 10rpx;

            .iconfont {
                font-size: 24rpx;
                color: var(--a-two-text-color);
            }
        }
    }

    .canvas_box {
        position: relative;
        height: 880rpx;
        background: var(--a-main-box-bg-color);
        border-radius: 20rpx;
        overflow: hidden;

        .upload_btn {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 10;
            width: 228rpx;
            height: 84rpx;
            border-radius: 45rpx;
            border: 3rpx solid var(--a-main-color);
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 10rpx;

            .iconfont {
                font-size: 32rpx;
                color: var(--a-one-text-color);
            }

            .text {
                font-size: 32rpx;
                color: var(--a-one-text-color);
            }
        }

        .clearBox {
            position: absolute;
            bottom: 20rpx;
            right: 20rpx;
            z-index: 999;
            color: var(--a-one-text-color);
            width: 59rpx;
            height: 59rpx;
            background-color: var(--a-one-text-color);
            background: rgba(0, 0, 0, 0.3);
            border-radius: 50%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;

            .iconfont {
                font-size: 36rpx;
            }

            .anewUpload {
                font-size: 22rpx;
            }
        }

        .imgCanvas {
            z-index: 2;
        }

        .smearCanvas {
            z-index: 3;
        }

        .eraseCanvas {
            z-index: 4;
        }


        .bgCanvas,
        .imgCanvas,
        .smearCanvas,
        .eraseCanvas {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }
    }

    .eraseAndsmear {
        display: flex;
        align-items: center;
        gap: 26rpx;
        margin-top: 31rpx;

        .left {
            flex-shrink: 0;
            width: 170rpx;
            height: 66rpx;
            background: var(--a-main-box-bg-color);
            border-radius: 33rpx;
            display: flex;
            align-items: center;
            justify-content: center;

            .smear,
            .erase {
                width: 82rpx;
                height: 60rpx;
                border-radius: 31rpx;
                display: flex;
                align-items: center;
                justify-content: center;
                color: var(--a-one-text-color);

                .iconfont {
                    font-size: 32rpx;
                }
            }

            .active {
                background: var(--a-main-color);
            }
        }

        .right {
            flex: 1;
        }
    }

    .textarea_box {
        margin-top: 31rpx;
    }

    .imgNum {
        display: flex;
        align-items: center;
        gap: 18rpx;

        .imgNum_item {
            box-sizing: border-box;
            width: 84rpx;
            height: 84rpx;
            border-radius: 12rpx;
            color: var(--a-one-text-color);
            background: var(--a-main-box-bg-color);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 8rpx;
            margin-top: 8rpx;

            &.active {
                border: 3rpx solid var(--a-main-color);
                color: var(--a-main-color);
            }

            .iconfont {
                font-size: 42rpx;
            }

            .text {
                font-size: 26rpx;
            }
        }
    }

}
</style>